import i18n, { t } from '@src/locales'
import './BizProcess.scss'

import _ from 'lodash'
/* 工单流程信息状态 */
import TaskStateEnum from '@model/enum/TaskStateEnum.ts';
import TaskStateProcessEnum from '@model/enum/TaskStateProcessEnum.ts'
import { TaskExceptionStateLabelEnum } from '@model/enum/LabelEnum.ts'

const TaskStateProcessArray = [
  TaskStateProcessEnum.DRAFT,
  TaskStateProcessEnum.CREATED,
  TaskStateProcessEnum.ALLOCATED,
  TaskStateProcessEnum.ACCEPTED,
  TaskStateProcessEnum.PROCESSING,
  TaskStateProcessEnum.FINISHED
]

/** 事件流程信息状态*/
const EventStateProcessArray = [
  {
    name: t('common.event.stateProcess.created'),
    value: 'created'
  },
  {
    name: t('common.event.stateProcess.allocated'),
    value: 'allocated',
  },
  {
    name: t('common.event.stateProcess.processing'),
    value: 'processing'
  },
  {
    name: t('common.event.stateProcess.finished'),
    value: 'finished',
  }
]

const ProcessItemWidth =  18;

const BizProcess = {
  name: 'biz-process',
  props: {
    /* 数据 工单/时间 */
    data: {
      type: Object,
      default: () => ({})
    },
    /* 类型流程信息设置 */
    flowSetting: {
      type: Object,
      default: () => ({})
    },
    /* 模式 */
    mode: {
      type: String,
      default: 'task'
    },
    /* 值 */
    value: {
      type: String,
      default: ''
    },
    // 超时时间
    flowOverTime:{
      type:Object,
      default:()=>({})
    },
    renderProcessExceptionFlag: {
      type:Boolean,
    },
    isDraft: {
      type:Boolean,
      default: false
    },
    collapseFlag:{
      type:Boolean,
    },
    flowNodeStatus: {
      type: Array,
      default: (() => [])
    },
    flowNodeTimes: {
      type: Array,
      default: (() => [])
    }
  },
  data() {
    return {
      taskStateProcessArray: TaskStateProcessArray,
      selected: ''
    }
  },
  computed: {
    /** 
     * @description 获取流程信息 
    */
    genStateProcess() {
      // 工单非草稿状态时删除草稿状态数据
      if (!this.isDraft) {
        this.taskStateProcessArray.forEach((item, ind) => {
          if (item.value == 'draft') this.taskStateProcessArray.splice(ind, 1)
        })
      }
      return this.mode === 'task' ? this.taskStateProcessArray : EventStateProcessArray
    },
    /* 获取当前状态的索引 */
    genCurrentStateIndex() {
      let index = 0;
      let state = null;
      
      for(let i = 0; i < this.genStateProcess.length; i++) {
        state = this.genStateProcess[i]
        if (this.isCurrentState(state)) {
          index = i
          break
        }
      }
      
      return index;
    },
    genExceptionStyle() {
      let genCurrentStateIndex = this.genCurrentStateIndex;
      let left = ProcessItemWidth * this.genCurrentStateIndex;
      return {
        left: `${ genCurrentStateIndex == 1 ? left + 39 : left }px`,
        top:'2px'
      }
    },
    // 判断是否是以取消
    isOffed() {
      return this.value === TaskStateEnum.OFFED.value
    },
    isException() {
      let { isPaused, isOverTime, taskException } = this.data
      return (isPaused === 1 || isOverTime === 1) || taskException
    },
    isOnceException() {
      let { onceOverTime, oncePaused, positionException, taskException } = this.data
      return (onceOverTime || oncePaused || positionException) || taskException
    },
    // 是否曾回退
    onceRollback() {
      return this.data.onceRollback == 1
    }
  },
  methods: {
    /* 获取流程信息状态的类名 */
    genStateProcessClassName(state, index) {
      let className = ['biz-process-state']
      let isSelected = Array.isArray(this.selected) ? _.isEqual(this.selected, state.value) : this.selected == state.value;
      
      state.isCurrent = this.genCurrentStateIndex == index
      state.isBefore = this.genCurrentStateIndex > index
      state.isAfter = this.genCurrentStateIndex < index
      state.isFirst = index == 0;
      state.isLast = index == this.genStateProcess.length - 1;
      state.isSelected = isSelected;
      
      state.isSelected && className.push('biz-process-state-selected')
      state.isCurrent && className.push('biz-process-state-current')
      state.isBefore && className.push('biz-process-state-before')
      state.isAfter && className.push('biz-process-state-after')
      state.isFirst && className.push('biz-process-state-first')
      state.isLast && className.push('biz-process-state-last')
      
      return className
    },
    genOverTime() {
      let { allot = {}, accept = {}, finish = {}, start = {} } = this.flowSetting;
      
      // 待分配
      let isCreated = this.judgeContainsState(TaskStateProcessEnum.CREATED.value)
      if(isCreated) {
        // return allot.overTime
        return this.flowOverTime['allot'] ?? ''
      }
      // 已指派
      if(this.value == TaskStateProcessEnum.ALLOCATED.value) {
        // return accept.overTime
        return this.flowOverTime['accept'] ?? ''
      }
      // 已接受
      if(this.value == TaskStateProcessEnum.ACCEPTED.value) {
        // 判断是否开启 开始节点
        let isHaveStartAction = start.state === true;
        // return isHaveStartAction ? start.overTime : ''
        return isHaveStartAction ? (this.flowOverTime['start'] ?? '') : ''
      }
      // 进行中
      if(this.value == TaskStateProcessEnum.PROCESSING.value) {
        // return finish.overTime
        return this.flowOverTime['finish'] ?? ''
      }
      
    },
    /* 判断是否是当前状态 */
    isCurrentState(state) {
      return state.value == this.value || (Array.isArray(state.value) && state.value.indexOf(this.value) > -1);
    },
    judgeContainsState(state) {
      return state.indexOf(this.value) > -1
    },
    /* 流程信息点击事件处理 */
    processClickHander(state) {
      if(state.isAfter) {
        return console.warn('Caused: because state is the after process state, So can not click')
      }
      
      this.selected = state.value;
      this.$emit('change', state);
    },
    /* 渲染流程信息状态 */
    renderProcessStateItem(h, state, index) {
      return (
        <div class="biz-process-state" onClick={ e => this.processClickHander(state) } class={ this.genStateProcessClassName(state, index) }>
          <span class="biz-process-left-triangle">
            <span class="biz-process-left-triangle-top"></span>
            <span class="biz-process-left-triangle-bottom"></span>
          </span>
          <span class="biz-process-state-name">{ state.name }</span>
          <span class="biz-process-right-triangle">
          </span>
        </div>
      )
    },
    /* 渲染流程异常状态显示 */
    renderProcessException(h) {
      if (this.mode === 'task') return this.renderTaskProcessExceptionState()

      return this.renderProcessExceptionState()
    },
    renderProcessExceptionState() {
      // 暂停
      let isPaused = this.data.isPaused == 1;
      // 超时
      let isOverTime = this.data.isOverTime == 1;
      
      if(isPaused) return this.renderProcessPaused();
      if(isOverTime) return this.renderProcessOverTime();
    },
    renderTaskProcessExceptionState() {
      let taskException = this.data.taskException
      let taskExceptionInfo = this.data.taskExceptionInfo

      if(taskException) return this.renderTaskProcessState(taskExceptionInfo)
    },
    renderProcessExceptionTextAndIcon(h) {
      if (this.mode === 'task') return this.renderTaskProcessExceptionTips()

      return this.renderProcessExceptionTips()
    },
    /* 渲染流程异常字段 */
    renderProcessExceptionTips() {
      // 曾超时
      let onceOverTime = this.data.onceOverTime === 1
      // 曾暂停
      let oncePaused = this.data.oncePaused === 1
      // 位置异常
      let positionException = this.data.positionException === 1
      // 是否是异常
      let isException = onceOverTime || oncePaused || positionException
      // 提示内容
      let content = []
      onceOverTime && content.push(t('common.event.exceptionStatus.onceOverTime'))
      oncePaused && content.push(t('common.event.exceptionStatus.oncePaused'))
      positionException && content.push(t('common.event.exceptionStatus.positionException'))
      
      let field = this.mode === 'event' ? t('common.base.eventAbnormal') : t('common.base.abnormal')
      
      return isException ? this.renderExceptionDom(field, content) : ''
    },
    /* 渲染工单流程异常字段 */
    renderTaskProcessExceptionTips() {
      // 工单异常
      const content = this.data.taskExceptionState || []
      const i18nContent = content.map(c => TaskExceptionStateLabelEnum[c] || c)
      const taskException = this.data.taskException
      
      return taskException ? this.renderExceptionDom(t('common.base.taskAbnormal') , i18nContent) : ''
    },
    /* 工单异常字段DOM */
    renderExceptionDom(field, content) {
      return (
        <div class="biz-process-exception-text">
          <el-tooltip content={ content.join(', ') } placement="top">
            <div>
              <i class="iconfont icon-info"></i>
              <span>{field}</span>
            </div>
          </el-tooltip>
        </div>
      )
    },
    /* 渲染工单暂停状态和原因 */
    renderTaskProcessState(exceptionInfo) {
      let style = {
        ...this.genExceptionStyle,
        color: TaskStateEnum.PSUSED.color
      }
      
      // 特殊适配
      if (this.isOnceException && this.genCurrentStateIndex == 0) {
        style.top = '2px'
        style.left = '60px'
      }

      let text = ''
      if(exceptionInfo && JSON.stringify(exceptionInfo) !== '{}'){
        let reason = exceptionInfo?.reason
        let action = TaskExceptionStateLabelEnum[exceptionInfo?.action] || exceptionInfo?.action || ''
        text = reason ? `${action} : ${reason}` : `${action}`
      }

      // 工单兼容超时
      let isOverTime = this.data.isOverTime == 1
      if(isOverTime) return this.renderProcessOverTime(text)

      return <div class="task-process-state" style={ style }> { text } </div>
    },
    /* 渲染工单状态暂停 */
    renderProcessPaused() {
      let style = {
        ...this.genExceptionStyle,
        color: TaskStateEnum.PSUSED.color
      }
      
      // 特殊适配
      if (this.isOnceException && this.genCurrentStateIndex == 0) {
        style.top = '2px'
        style.left = '30px'
      }
      
      return <div style={ style }> {t('common.task.status.paused')} </div>
    },
    /* 渲染工单状态超时 */
    renderProcessOverTime(text) {
      let index = this.genCurrentStateIndex + .5
      let style = {
        left: `${ProcessItemWidth * index}px`,
        color: TaskStateEnum.PSUSED.color
      }
      let overTime = this.genOverTime();

      let overTimeText = text ? text : t('common.base.timedOut')
      let overTimeDom = <span class="biz-process-exception-time">{ overTime }</span>
      
      return (
        <div style={ style }> 
          { overTimeText } 
          { overTime ? overTimeDom : '' }
        </div>
      )
    },
    stateFilterHandler(value) {
      return this.taskStateProcessArray = this.taskStateProcessArray.filter(state => state.value != value);
    },
    // 取消更新状态
    updateAllState(allState) {
      // 已取消，且 未回退过
      if(this.isOffed && !this.onceRollback) {
        // 根据是否有接单时间判断 是否包含流程 已指派
        let allotTime = this.data.allotTime
        // 根据是否有接单时间判断 是否包含流程 已接受
        let acceptTime = this.data.acceptTime
        // 根据是否有接单时间判断 是否包含流程 进行中
        let startTime = this.data.startTime

        this.taskStateProcessArray = allState.slice();

        !allotTime && this.stateFilterHandler(TaskStateEnum.ALLOCATED.value)
        !acceptTime && this.stateFilterHandler(TaskStateEnum.ACCEPTED.value)
        !startTime && this.stateFilterHandler(TaskStateEnum.PROCESSING.value)

        // 没有进行的自定义移除
        this.flowNodeTimes?.map(item => {
          if(!item.time) {
            this.stateFilterHandler(item.key)
          }
        })

        this.taskStateProcessArray.pop()
        this.taskStateProcessArray.push(TaskStateProcessEnum.OFFED)
      }
    }
  },
  created() {
    this.updateAllState(TaskStateProcessArray);
  },
  render(h) {
    // 曾回退的 已取消特殊处理
    if(this.isOffed && this.onceRollback) {
      return <div class="biz-process-offed" style={{ backgroundColor: TaskStateEnum.OFFED.color }}>{ TaskStateEnum.OFFED.name }</div>
    }
    if (this.collapseFlag) {
       return (
        <div class="biz-process-block">
         { 
           this.isException || this.isOnceException
             ? (
               <div class="biz-process-exception">
                 { this.renderProcessExceptionTextAndIcon(h) }
                 { this.renderProcessException(h) }
                </div>
             )
             : null
         }
        </div> 
      )
    } else if (!this.collapseFlag&&this.renderProcessExceptionFlag) {
      return (
        <div class="biz-process-block">
          <div class="biz-process" style="overflow: none">
            {
              this.genStateProcess.map((state, index) => {
              if (state.isCurrent || this.genCurrentStateIndex == index) {
                return (
                  <div class="biz-process-state biz-process-state-before">
                    <span class="biz-process-left-triangle">
                      <span class="biz-process-left-triangle-top"></span>
                      <span class="biz-process-left-triangle-bottom"></span>
                    </span>
                    <span class="biz-process-state-name">{state.name}</span>
                    <span class="biz-process-right-triangle">
                    </span>
                  </div>
                )
             }
            })}
            {
              this.data?.attribute?.intelligentCheckStateStr == 1
                ? (
                  <div class="biz-process-intelligent"><i class="iconfont icon-info"></i>{t('common.task.qualityTestingStatus.abnormal')}</div>
                )
                : null
            }
            { 
           this.isException || this.isOnceException
             ? (
               <div class="biz-process-exception">
                 { this.renderProcessExceptionTextAndIcon(h) }
                 { this.renderProcessException(h) }
                </div>
             )
             : null
         }
          </div>
        </div> 
      )
    } else {
       return (
        <div class="biz-process-block">
          <div class="biz-process" style="overflow:hidden">
            { this.genStateProcess.map((state, index) => this.renderProcessStateItem(h, state, index)) }
            {
            this.data?.attribute?.intelligentCheckStateStr == 1 
              ? (
                <div class="biz-process-intelligent"><i class="iconfont icon-info"></i>{t('common.task.qualityTestingStatus.abnormal')}</div> 
              )
              : null
            }
          </div>
        </div>
      )
    }
  },
  watch: {
    flowNodeStatus: {
      handler(val) {
        if(val?.length) {
          this.taskStateProcessArray = [TaskStateProcessEnum.DRAFT, ...val];
          this.updateAllState(val);
        }
      }
    }
  }
}

export default BizProcess;